운영체제·시스템 용어
OS, 프로세스, IPC, 캐시, DB 등 시스템 동작 용어
- 용어 49개
OS (Operating System, 운영체제)
CPU, 메모리, 디스크 같은 하드웨어 자원을 관리하고 프로그램이 쓸 수 있게 해 주는 기본 소프트웨어.
- 예) Linux, Windows.
- 학습 노트: 리눅스 커널 학습 로드맵 · 리눅스 기본 사용 및 시스템 개념 정리
kernel (커널)
운영체제의 핵심 부분. 하드웨어를 직접 제어하고 프로세스, 메모리, 파일, 네트워크를 관리한다.
- 메모리는 커널 영역(kernel space)과 사용자 영역(user space)으로 나뉜다. 커널은 커널 영역에서 실행되고, 일반 프로그램은 사용자 영역에서 실행된다.
- 사용자 영역은 커널의 일부가 아니다. 사용자 프로그램은 system call로 커널에 기능을 요청한다.
- 학습 노트: 리눅스 커널 학습 로드맵
system call (시스템 콜)
사용자 프로그램이 커널 기능을 요청하는 공식 통로.
- 예) open, read, write, fork.
- 학습 노트: 리눅스 시스템 함수(System Call) 카테고리별 치트시트 — 파일·프로세스·시그널·네트워크·계정정보
process / thread
process는 실행 중인 프로그램(독립된 주소 공간), thread는 프로세스 안의 실행 흐름 단위(주소 공간 공유).
- 관련 노트: IPC와 스레드 메모리 공유 비교
- 학습 노트: 프로세스와 좀비 프로세스 (fork·waitpid) · pthread 멀티스레드 API 레퍼런스 · 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
daemon (데몬)
백그라운드에서 계속 실행되며, 터미널 세션과 연결되지 않은 채 요청을 기다리거나 주기적으로 일하는 프로세스.
- 일반 프로그램과 달리 로그인한 터미널을 닫아도 계속 돈다. 사용자와 직접 입출력을 주고받지 않는다.
- 이름 끝에 d를 붙이는 관례가 있다. 예) sshd, httpd, systemd.
- 쉘에서
명령 &로 띄운 백그라운드 작업은 터미널 세션이 끊기면 같이 종료될 수 있어 daemon과 다르다. 요즘은 systemd 같은 서비스 관리자가 daemon을 띄우고 관리한다. - Windows에서는 비슷한 개념을 “서비스(Service)“라고 부른다.
- 학습 노트: 4. 데몬 골격 — 순수 POSIX main 초기화·시그널·스레드·폴링루프 · D7. 데몬 — 시그널·poll·워커큐·graceful shutdown
signal (시그널)
프로세스에 “어떤 일이 생겼다”고 비동기로 알리는 소프트웨어 신호.
- 보내는 주체는 커널만이 아니다. 커널(예: 잘못된 메모리 접근 감지), 다른 프로세스(
kill명령), 사용자(터미널에서 Ctrl+C), 프로세스 자기 자신 모두 보낼 수 있다. - 받은 프로세스는 기본 동작(대개 종료)을 하거나, 핸들러를 등록해 직접 처리하거나, 무시할 수 있다. 단 SIGKILL, SIGSTOP은 처리·무시할 수 없다.
- SIGINT(2): Ctrl+C 중단 요청 / SIGTERM(15): 정상 종료 요청 / SIGKILL(9): 강제 종료 / SIGSEGV(11): 잘못된 메모리 접근(segmentation fault) / SIGHUP(1): 터미널 연결 끊김, daemon에서는 설정 다시 읽기 용도로 쓰는 관례 / SIGCHLD: 자식 프로세스 종료 알림
- 종료할 때는 먼저 SIGTERM으로 정리할 기회를 주고, 응답이 없을 때 SIGKILL을 쓰는 것이 일반적이다.
- 학습 노트: 1. 비정상 종료 시그널 종류 — SIGSEGV·SIGABRT·SIGBUS·SIGILL·SIGFPE 개관 · 2. 시그널별 원인 분석 — 각 시그널이 실제로 왜 발생하는가 · GDB 실전 디버깅 (멀티스레드·시그널) · which vs command -v, 프로세스 종료 시그널 - which vs command v, 프로세스 종료 시그널
IPC (Inter-Process Communication)
프로세스끼리 데이터를 주고받는 방법.
- 종류: pipe, message queue, shared memory, socket 등. semaphore는 주로 동기화에 쓰이지만 IPC로 분류되기도 한다.
- 학습 노트: System V IPC 개념 (메시지 큐·세마포어·공유메모리) · 메시지 큐 API (msgget·msgsnd·msgrcv·msgctl)
shared memory (공유 메모리)
여러 프로세스가 같은 물리 메모리 영역을 각자의 주소 공간에 연결해서 함께 쓰는 방식.
- 데이터를 복사하지 않아 IPC 중 가장 빠르다.
- 동시에 접근하면 값이 깨질 수 있어 semaphore나 mutex 같은 동기화가 필요하다.
- 학습 노트: System V IPC 개념 (메시지 큐·세마포어·공유메모리) · IPC와 스레드 메모리 공유 비교
pipe (파이프)
한 프로세스의 출력을 다른 프로세스의 입력으로 잇는 단방향 바이트 흐름 통로.
- 쉘의
ls | grep txt가 대표적이다. 이름이 있는 파이프는 named pipe(FIFO).
message queue (메시지 큐)
프로세스 사이에 메시지(덩어리 단위)를 큐에 넣고 꺼내며 주고받는 방식.
semaphore / mutex (세마포어 / 뮤텍스)
동시 접근을 제어하는 도구. mutex는 한 번에 하나만 들어가게 하는 잠금, semaphore는 동시에 N개까지 허용하는 카운터.
- 관련 노트: 세마포어와 동시성 제어
- 학습 노트: 세마포어 & 뮤텍스 ( JAVA LOCK )
concurrency / parallelism (동시성 / 병렬성)
동시성은 여러 작업이 겹쳐서 “함께 진행되는 것처럼” 처리되도록 구조를 짜는 것, 병렬성은 실제로 같은 순간에 여러 작업이 여러 CPU 코어에서 실행되는 것.
- 철자는 concurrency다. 동시성은 코어가 하나여도 작업을 번갈아 실행하면 성립한다(예: 요리사 한 명이 여러 요리를 번갈아 하는 것). 병렬성은 요리사가 여러 명이어야 한다.
- 서버에서 동시성이 중요한 이유: 여러 요청이 같은 데이터나 자원을 동시에 건드리기 때문에 순서에 따라 결과가 달라지는 문제(race condition, deadlock)가 생긴다. 이를 막는 것이 동시성 제어다(mutex, semaphore, CAS, DB 락 등).
- 관련: 멀티스레드, 비동기 처리, 분산 락.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation · 병렬성, 싱글-멀티스레드 서버, 세마포어, 병렬 자료구조
스레드 공유 영역 vs 전용 영역
같은 프로세스 안의 스레드끼리 무엇을 함께 쓰고 무엇을 각자 갖는지의 구분.
- 공유: heap, 전역·static 변수, 코드 영역, 열린 파일. 여러 스레드가 동시에 접근하므로 동기화가 필요하다(race condition의 원인).
- 전용: 각 스레드의 stack(지역 변수), CPU 레지스터, 그리고 TLS(thread-local storage). 다른 스레드가 건드리지 않아 동기화가 필요 없다.
- heap은 프로세스 하나에 하나이고 모든 스레드가 같은 heap을 쓴다(“스레드별 heap”이라는 영역은 따로 없다). 다만 성능을 위해 할당기가 스레드마다 heap의 일부를 미리 떼어 주는 경우가 있다. 예) glibc malloc의 스레드별 arena, Java의 TLAB(Thread-Local Allocation Buffer). 이 조각에서 할당만 스레드별로 하고, 만들어진 객체는 다른 스레드도 볼 수 있다.
- 관련 노트: IPC와 스레드 메모리 공유 비교
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
TLS (Thread-Local Storage) / ThreadLocal
스레드마다 따로 갖는 전용 저장 공간. 같은 이름의 변수라도 스레드마다 별개의 값을 가진다. “공유” 공간이 아니라 “공유하지 않는” 공간이다.
- 락 없이도 스레드끼리 값이 섞이지 않아서, 요청마다 따로 들고 다녀야 하는 정보(사용자 정보, trace ID, 트랜잭션)를 파라미터로 넘기지 않고 보관하는 데 쓴다.
- 예) Java
ThreadLocal, C의__thread/ C++의thread_local, POSIXpthread_key_*. C의errno도 스레드별로 따로 있다. - 주의 1: 스레드 풀은 스레드를 재사용하므로, 요청이 끝나면
remove()로 지우지 않으면 다음 요청에 이전 값이 남는다(오염, 메모리 누수). - 주의 2: 비동기 처리로 작업이 다른 스레드로 넘어가면 값이 따라가지 않는다. 그래서 context propagation이 따로 필요하다(MSA·분산 시스템 노트의 분산 추적 참고).
- 보안 용어의 TLS(Transport Layer Security)와 약어가 같으니 문맥으로 구분한다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation · 분산 추적(Distributed Tracing)과 비동기 스레드 컨텍스트 전파 아키텍처 (TraceContext, Netty, Spring Batch)
thread pool (스레드 풀)
스레드를 미리 일정 수 만들어 두고, 작업이 올 때마다 하나씩 꺼내 쓰고 끝나면 반납해 재사용하는 구조. “미리 만들어 둔 스레드 묶음 + 작업 대기열(task queue)“이다.
- 요청마다 스레드를 만들고 없애면 생성·소멸 비용(시간, 스택 메모리)이 들고, 요청이 몰릴 때 스레드가 무한정 늘어 서버가 무너질 수 있다. 풀은 이 둘을 막는다.
- 동작: 작업 제출 → 대기열에 쌓임 → 놀고 있는 worker 스레드가 꺼내 실행 → 끝나면 다시 대기. 풀 크기가 동시에 실행되는 작업 수의 상한이 된다.
- 크기 가이드: CPU를 쓰는 작업은 코어 수 근처, 대기(I/O, 외부 호출)가 많은 작업은 더 크게 잡는다. 대기열이 가득 차면 거부 정책(예외 발생, 호출한 스레드가 직접 실행, 버림)을 정한다.
- Java의
ExecutorService/ThreadPoolExecutor(core·max 크기, 대기열, 거부 정책)가 대표적이다. - 주의: 모든 스레드가 느린 호출에 묶이면 thread pool exhaustion, 대기열을 무한으로 두면 메모리 부족(OOM), 풀 안의 작업이 같은 풀의 다른 작업을 기다리면 deadlock, 스레드를 재사용하므로 ThreadLocal은 요청이 끝날 때 지워야 한다.
- 학습 노트: 01. Netty 아키텍처와 이벤트 루프 스레드 모델 (EventLoop, Boss·Worker, Bootstrap) · 스레드별 전용 큐와 해시 샤딩 — 락 경합 없는 고성능 워커 패턴 · 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
thread-safe (스레드 안전)
여러 스레드가 동시에 접근해도 결과가 올바른 코드나 자료구조.
- 예) Java의
ConcurrentHashMap은 thread-safe,HashMap은 아니다. thread-safe하지 않은 객체를 여러 스레드가 공유하면 race condition이 생긴다. - 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
reentrant (재진입 가능)
함수가 실행되는 도중에 다시 호출되어도(재귀, 다른 스레드, 시그널 핸들러에서의 호출) 올바르게 동작하는 성질.
- 조건: 전역 변수나 static 변수 같은 공유 상태를 건드리지 않고, 호출자가 넘긴 값과 지역 변수만 쓰고, 재진입 불가능한 함수를 호출하지 않는다.
- 예) C의
strtok은 내부 static 상태를 써서 재진입 불가이고,strtok_r(reentrant)은 상태를 호출자가 넘긴다.localtime과localtime_r도 같은 관계다. - thread-safe와 비슷하지만 같지 않다. 재진입 가능하면 보통 thread-safe지만, 락으로 thread-safe하게 만든 함수는 같은 스레드가 도중에 다시 호출하면 deadlock이 날 수 있어 재진입 불가일 수 있다.
- 시그널 핸들러 안에서는 재진입 가능한(async-signal-safe) 함수만 안전하게 쓸 수 있다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
reentrant lock (재진입 락)
이미 그 락을 쥔 스레드가 같은 락을 다시 얻어도 막히지 않는 락.
- Java의
synchronized와ReentrantLock이 해당한다. 락을 쥔 메서드가 같은 락이 필요한 다른 메서드를 호출할 때 스스로 deadlock에 빠지지 않는다. 몇 번 얻었는지 세어 두었다가 같은 횟수만큼 풀어야 완전히 해제된다. - 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
스레드 동시성 문제 한눈에 보기
여러 스레드가 함께 돌 때 생기는 대표적인 오류들. 이름이 비슷해 헷갈리므로 증상 기준으로 구분한다.
| 문제 | 증상 | 대표 원인 | 대응 |
|---|---|---|---|
| race condition | 실행 순서에 따라 결과가 달라짐, 가끔만 틀림 | 공유 자원 동시 접근 | lock, atomic, CAS |
| data race | 동기화 없는 동시 읽기/쓰기 | 보호 없이 공유 변수 사용 | 동기화, 불변 객체 |
| deadlock | 스레드들이 영원히 멈춤 | 서로 상대의 락을 기다림 | 락 순서 통일, timeout |
| livelock | CPU는 쓰는데 진전이 없음 | 서로 양보만 반복 | 무작위 대기(backoff) |
| starvation | 특정 스레드만 계속 못 실행됨 | 불공정한 락, 낮은 우선순위 | 공정 락, aging |
| priority inversion | 높은 우선순위가 오래 대기 | 낮은 우선순위가 락을 쥐고 있음 | priority inheritance |
| visibility / reordering | 다른 스레드가 바뀐 값을 못 봄 | CPU 캐시, 컴파일러·CPU 명령 재배치 | volatile, memory barrier |
| 원자성 위반 (check-then-act) | 검사와 실행 사이에 상태가 바뀜 | 여러 단계를 한 덩어리로 묶지 않음 | 락으로 묶기, 원자적 연산 |
race condition (경쟁 상태)
여러 스레드가 같은 자원에 접근하고, 실행 순서(타이밍)에 따라 결과가 달라지는 문제.
- 예) 두 스레드가
count++를 동시에 실행.count++는 읽기 → 더하기 → 쓰기 3단계라서, 둘 다 5를 읽고 각자 6을 쓰면 7이어야 할 값이 6이 된다(갱신 손실, lost update). - 재현이 어렵고 가끔만 터지는 것이 특징이다. 해결: lock으로 구간을 보호하거나 atomic 연산, CAS를 쓴다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
data race
동기화 없이 여러 스레드가 같은 메모리에 동시에 접근하고, 그중 하나 이상이 쓰기인 상태.
- race condition의 대표적인 원인이다. C/C++에서는 data race가 있으면 동작이 정의되지 않는다(undefined behavior). 모든 race condition이 data race인 것은 아니고, 락을 써도 검사와 실행 사이에 끼어드는 논리적 race condition은 남을 수 있다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
deadlock (교착 상태)
둘 이상의 스레드가 서로 상대가 쥔 락을 기다리며 영원히 멈추는 상태.
- 예) 스레드 1은 락 A를 잡고 B를 기다리고, 스레드 2는 락 B를 잡고 A를 기다린다.
- 발생 조건 4가지(Coffman): 상호 배제, 점유하며 대기, 비선점(빼앗을 수 없음), 순환 대기. 하나라도 깨면 막을 수 있다.
- 예방: 모든 스레드가 락을 같은 순서로 잡기, 락 획득에 timeout 두기(
tryLock), 락을 잡고 있는 구간을 짧게 하기. - 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
livelock
스레드가 멈춰 있지는 않지만 서로 양보하며 상태만 바꾸고 일은 진전되지 않는 상태.
- 복도에서 마주 오는 두 사람이 서로 비켜 주다가 계속 같은 방향으로 움직이는 것과 같다. 재시도 간격을 무작위로 섞는(backoff) 식으로 푼다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
starvation (기아)
특정 스레드가 자원(락, CPU)을 계속 얻지 못해 실행되지 못하는 상태.
- 우선순위가 낮거나 락이 불공정하게 늘 다른 스레드에게 돌아가는 경우에 생긴다. 공정(fair) 락을 쓰거나 오래 기다린 스레드의 우선순위를 올리는 aging으로 푼다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
priority inversion (우선순위 역전)
높은 우선순위 스레드가 낮은 우선순위 스레드가 쥔 락을 기다리는데, 중간 우선순위 스레드가 낮은 쪽을 계속 밀어내서 높은 쪽이 오래 대기하는 현상.
- priority inheritance(락을 쥔 스레드의 우선순위를 일시적으로 올림)로 푼다. 1997년 화성 탐사선 Pathfinder에서 겪은 사례로 알려져 있다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
visibility / reordering (가시성 / 명령 재배치)
한 스레드가 바꾼 값을 다른 스레드가 보지 못하거나, 예상과 다른 순서로 보이는 문제.
- 원인: 값이 CPU 캐시나 레지스터에 머물러 있거나, 컴파일러·CPU가 성능을 위해 명령 순서를 바꾸기 때문.
- 해결: Java의
volatile, 락, memory barrier로 “먼저 일어난 일이 다른 스레드에 보이도록” 보장한다(happens-before). - 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
atomicity violation (check-then-act)
“검사하고 나서 실행”하는 사이에 다른 스레드가 상태를 바꿔서 검사 결과가 무효가 되는 문제.
- 예)
if (!map.containsKey(k)) map.put(k, v);사이에 다른 스레드가 같은 키를 넣을 수 있다. 검사와 실행을 락으로 묶거나putIfAbsent같은 원자적 연산을 쓴다. - 보안에서는 TOCTOU(time-of-check to time-of-use)라 부르기도 한다.
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
thread pool exhaustion (스레드 풀 고갈)
모든 스레드가 응답을 기다리며 묶여서 새 요청을 처리할 스레드가 없는 상태.
- 느린 외부 호출에 timeout이 없을 때 생기고, 연쇄 장애로 번진다(MSA·분산 시스템 노트의 cascading failure, bulkhead 참고).
- 학습 노트: 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation · 장애 전파 방지 패턴 - Circuit Breaker·Bulkhead·Retry·Rate Limit
endian (little endian / big endian)
멀티바이트 값(정수 등)을 메모리에 저장할 때 바이트를 어떤 순서로 놓느냐의 규칙(바이트 순서, byte order).
- little endian은 낮은 주소에 값의 낮은 자리 바이트부터, big endian은 낮은 주소에 값의 높은 자리 바이트부터 저장한다. “큰 주소부터 읽는다”가 아니라 “어느 자리의 바이트를 낮은 주소에 두느냐”가 기준이다.
- 비트 순서가 아니라 바이트 순서다. 1바이트 값(char, 문자열의 한 글자)은 영향이 없다.
- x86, 대부분의 ARM 환경은 little endian이다. 네트워크 전송은 big endian으로 약속되어 있다(네트워크 바이트 순서).
- 다른 endian 시스템끼리 바이너리 데이터를 주고받거나 파일로 읽으면 값이 뒤집혀 보인다. 그래서 전송 전후에 변환해야 한다(C의
htons/htonl/ntohs/ntohl). - 학습 노트: 리틀엔디안-빅엔디안 · 엔디안(바이트 순서)과 인터넷 체크섬 — LSB·MSB와 htons를 직접 만들어보기 · 3. 바이트 골격 — 비트플래그·엔디안·Pack·Unpack
0x12345678(4바이트 정수)을 주소 0x100부터 저장할 때:
| 주소 | 0x100 | 0x101 | 0x102 | 0x103 |
|---|---|---|---|---|
| big endian | 12 | 34 | 56 | 78 |
| little endian | 78 | 56 | 34 | 12 |
- big endian: 낮은 주소에 값의 가장 높은 자리 바이트(12)가 온다. 사람이 숫자를 쓰는 순서와 같다.
- little endian: 낮은 주소에 값의 가장 낮은 자리 바이트(78)가 온다.
stream (스트림)
데이터를 경계 없이 순서대로 연속해서 흘려보내고, 받는 쪽이 필요한 만큼 순차 처리하는 방식.
- TCP는 바이트 스트림이다. 메시지 경계는 상위 프로토콜이 정한다.
- HTTP/2의 stream은 하나의 연결 안에서 독립적으로 오가는 요청-응답 흐름 하나를 가리킨다(여러 개가 동시에 가능).
panic (패닉)
복구할 수 없는 치명적인 오류를 만나 프로그램이나 커널이 스스로 멈추는 것.
- 커널 panic: OS 전체가 중단된다. Go, Rust 등의 panic: 프로그램이 중단된다(처리하지 않으면 종료).
- 원인은 하드웨어 장애일 수도 있지만 코드 버그, 메모리 오류인 경우도 많다.
segmentation fault / core dump
segmentation fault는 허용되지 않은 메모리에 접근해서 OS가 프로세스를 강제로 종료하는 것, core dump는 그 순간의 메모리 상태를 저장한 파일.
- 원인 분석에 core dump를 디버거로 연다.
- 학습 노트: 3. Core Dump 확인 방법 — 활성화·수집·gdb 분석 · 2. 시그널별 원인 분석 — 각 시그널이 실제로 왜 발생하는가
gdb (GNU Debugger)
C/C++ 프로그램을 디버그하는 대표적인 도구. Go, Rust 등도 일부 지원한다.
- 실행 중인 프로세스를 멈추고 변수, 메모리, 호출 순서를 확인한다. 이미 떠 있는 프로세스에 붙을 수도 있고(
gdb -p PID), 프로그램이 죽으면서 남긴 core dump를 열어 원인을 분석할 수도 있다(gdb 프로그램 core). - 자주 쓰는 명령:
break(중단점),run,next/step(한 줄 실행),print(변수 확인),bt(backtrace, 호출 순서 확인). - 컴파일할 때 디버그 정보(
-g옵션)를 넣어야 변수명과 소스 줄을 볼 수 있다. - 학습 노트: GDB 실전 디버깅 (멀티스레드·시그널) · Mac 전용 GDB 컴파일_(LLDB, Clang) · 3. Core Dump 확인 방법 — 활성화·수집·gdb 분석
memory leak (메모리 누수)
사용이 끝난 메모리를 반납(해제)하지 않아, 정리되지 못한 메모리가 계속 쌓이는 상태.
- 시간이 지날수록 사용량이 늘어 느려지거나 결국 메모리 부족으로 프로세스가 종료된다.
- GC가 있는 언어도 불필요한 참조가 남아 있으면 같은 문제가 생긴다.
- 학습 노트: 메모리 누수 찾기 · 계층적 스트리밍 파이프라인 설계로 OOM 방지 · 대용량 트래픽 로깅 메모리 누수(OOM) 방지 패턴
heap vs stack (메모리 영역)
stack은 함수 호출 때 지역 변수가 자동으로 쌓이고 함수가 끝나면 자동으로 사라지는 영역, heap은 실행 중에 필요한 만큼 직접 할당하고 직접(또는 GC가) 해제하는 영역.
- stack은 빠르고 크기가 작다. 너무 깊게 호출하면 stack overflow가 난다. 자료구조 stack(LIFO)과 같은 방식으로 동작한다(개발 기본 노트 참고).
- heap은 크기가 크고 유연하지만 해제를 잊으면 메모리 누수가 생긴다.
- 학습 노트: 메모리 구조 · 메모리 구조 및 const · 동적할당
malloc / free (동적 메모리 할당)
C에서 실행 중에 heap의 메모리를 요청하는 함수(malloc)와 반납하는 함수(free).
malloc(100)은 100바이트를 확보해 그 주소를 돌려준다. 실패하면 NULL을 반환하므로 확인해야 한다. 쓰고 나면 반드시free로 반납해야 한다.- free를 빼먹으면 memory leak, 이미 free한 주소를 쓰면 segmentation fault 같은 오류가 난다. C++의
new/delete가 같은 역할이다. - 실제로 OS에서 메모리를 받아 잘라 주는 일은 메모리 할당기(glibc malloc, jemalloc 등)가 한다(성능·관측·로그 노트 참고).
- 학습 노트: 동적할당 · 동적 할당 소유권 — caller free vs callee create·destroy 쌍 · 성능 분석 도구와 관측 - perf·flame graph·eBPF·메모리
OOM (Out Of Memory)
메모리가 부족해서 더 할당할 수 없는 상태 또는 그 오류.
- heap에만 한정되지 않는다. 프로세스 안에서는 힙이 가득 차면 OOM이 나고(예: Java
OutOfMemoryError: Java heap space), 시스템·컨테이너 전체 메모리가 부족하면 OS의 OOM killer가 프로세스를 강제 종료한다(OOM Kill, 성능·관측·로그 노트 참고). - 원인은 단순히 사용량이 많은 경우와 memory leak으로 계속 쌓이는 경우로 나뉜다.
- 학습 노트: 계층적 스트리밍 파이프라인 설계로 OOM 방지 · 대용량 트래픽 로깅 메모리 누수(OOM) 방지 패턴 · 성능 분석 도구와 관측 - perf·flame graph·eBPF·메모리
CAS (Compare-And-Swap)
“현재 값이 내가 기대한 값과 같을 때만 새 값으로 바꾼다”를 CPU가 한 번에(원자적으로) 처리하는 명령. 락 없이 동시성을 다루는 기반이다.
- 동작:
CAS(주소, 기대값, 새값)→ 주소의 현재 값이 기대값과 같으면 새 값으로 바꾸고 성공, 다르면(그 사이에 다른 스레드가 바꿨으면) 실패. 실패하면 다시 읽고 재시도한다. - 예) 카운터 증가: 현재 값을 읽어 5라고 기억 →
CAS(counter, 5, 6)시도 → 그 사이 다른 스레드가 6으로 바꿨다면 실패 → 다시 읽어서 재시도. Java의AtomicInteger.incrementAndGet()가 이 방식이다. - 락(mutex)과 달리 대기하며 잠들지 않아 context switching이 없고(lock-free), 데이터베이스의 낙관적 락(
version컬럼 비교)과 같은 발상이다. - 단점: 경쟁이 심하면 재시도가 계속 반복되고, 값이 A → B → A로 바뀌면 변화가 없었다고 착각하는 ABA 문제가 있다(버전 번호를 함께 비교해 해결한다).
- 원자성이 필요한 이유와 race condition은 앞의 항목, 낙관적 락은 데이터·캐시·저장소 노트 참고.
- 학습 노트: 락 없는 카운터 — GCC 원자적 연산 빌트인과 C11 atomic · 가상 스레드(Virtual Thread) 기반 고가용성 분산 배치 엔진 설계 (Atomic CAS, 이중 큐, 자가 치유) · 스레드 동시성 문제 정리 - race·deadlock·livelock·starvation
cache (캐시)
자주 쓰는 데이터를 더 빠른 곳에 임시로 보관해 두는 것.
local cache (로컬 캐시)
그 프로세스나 서버 안(주로 메모리)에 둔 캐시.
- 빠르지만 서버마다 따로 가지므로 서로 값이 달라질 수 있다. 여러 서버가 같이 쓰는 캐시는 분산(공유) 캐시(예: Redis)라고 부른다.
- 학습 노트: 캐시 전략과 운영 이슈 - Redis·stampede·무효화·write-behind
write-through / write-behind (write-back)
캐시에 쓴 데이터를 원본 저장소(DB 등)에 언제 반영하느냐에 따른 쓰기 방식.
- write-through: 캐시와 DB에 동시에 쓴다(동기). 안전하지만 쓰기가 느리다.
- write-behind(= write-back): 캐시에만 먼저 쓰고 응답한 뒤, DB에는 나중에 모아서 비동기로 반영한다. 쓰기가 빠르고 DB 부하가 줄지만, 반영 전에 캐시가 죽으면 그 데이터가 유실될 수 있다.
- “나중에 쓰기”는 맞지만 DB에만 쓰이는 말이 아니다. 캐시, 디스크 버퍼 등 “빠른 쪽에 먼저 쓰고 느린 쪽에 나중에 반영”하는 모든 경우에 쓴다.
- 학습 노트: 캐시 전략과 운영 이슈 - Redis·stampede·무효화·write-behind
stale (스테일)
원본이 바뀌었는데 갱신되지 않아 현재와 어긋난, 낡은 상태의 데이터·연결·세션·캐시.
- 단지 “오래됐다”가 아니라 “더 이상 믿으면 안 되는 값”이라는 뜻이다. 그래서 갱신하거나 폐기하거나 다시 조회하는 처리(핸들링)가 필요하다.
- 예) stale cache, stale connection.
- 학습 노트: 캐시 전략과 운영 이슈 - Redis·stampede·무효화·write-behind
stateless / stateful
서버가 요청 사이의 상태를 기억하지 않으면 stateless, 기억하면 stateful.
- stateless는 서버를 늘리고 장애를 복구하기 쉽다.
DB (Database, 데이터베이스)
데이터를 구조적으로 저장하고 조회·수정·삭제하는 시스템.
- RDBMS(테이블과 SQL)와 NoSQL(키-값, 문서 등)로 크게 나눈다.
- 학습 노트: 이론 데이터베이스 개론
transaction (트랜잭션)
여러 작업을 하나처럼 처리하는 단위. 전부 성공하거나 전부 취소된다.
- 보통 ACID(원자성, 일관성, 고립성, 지속성)로 설명한다.
- 학습 노트: 스프링이 제공해주는 트랜잭션 이해하기 · 순수 JDBC와 트랜잭션 이해하기
CRUD
Create(생성), Read(조회), Update(수정), Delete(삭제). 데이터를 다루는 기본 4가지 동작.
- HTTP 메서드와의 대응은 네트워크·통신 노트 참고.
- 학습 노트: DML (select, insert, update, delete)
System V IPC / POSIX IPC
프로세스 간 통신 자원(메시지 큐, 공유메모리, 세마포어)을 제공하는 두 가지 인터페이스 계열.
- System V: 숫자 key로 찾고, 핸들(
msqid)이 파일 디스크립터가 아니다(epoll에 넣을 수 없다). 상태는ipcs로 본다. - POSIX: 이름(
"/name")으로 찾고, Linux에서는 메시지 큐 디스크립터가 파일 디스크립터라epoll에 넣을 수 있다. - 둘 다 프로세스가 끝나도 자원이 커널에 남는다. 직접 삭제해야 한다.
- 학습 노트: POSIX IPC와 System V IPC 비교 — 메시지 큐 중심
Unix domain socket (유닉스 도메인 소켓)
같은 장비의 프로세스끼리 통신하는 소켓. 주소가 IP:포트가 아니라 파일 경로다(AF_UNIX).
ls -l에서 파일 종류가s로 보인다.- 상대가 종료하면 연결이 닫혀 서버가 즉시 알 수 있다. 그래서 클라이언트 프로세스의 생사 감시에 쓰이기도 한다. 메시지 큐나 공유메모리는 상대가 죽어도 아무 일도 일어나지 않는다.
msgmax / msgmnb / msgmni (메시지 큐 커널 한도)
System V 메시지 큐의 커널 한도. msgmax는 메시지 1건의 최대 크기, msgmnb는 큐 하나에 쌓을 수 있는 총 바이트, msgmni는 시스템 전체 큐 개수.
/proc/sys/kernel/아래에서 확인한다.msgmni기본값은 Linux 3.19부터 32,000이고, 넘으면msgget이ENOSPC로 실패한다. 큐를 만들면msg_qbytes가msgmnb값으로 설정된다.- 소프트웨어가 요청한 메시지 크기가
msgmax보다 크면 줄여서 쓰는 경우가 있다. - 학습 노트: POSIX IPC와 System V IPC 비교 — 메시지 큐 중심